﻿/* Muaz Khan – http://dashingquill.web.officelive.com */

using System;
using System.Linq;
using DTweet.Models;

namespace DTweet.Helpers
{
    /***********************************
    * All accounts related extension methods goes here
    ***********************************/
    public static class AccountsHelperExtensions
    {
        public static string ResolveForUserName(this string input)
        {
            return input.Replace(" ", "").Replace("(", "").Replace(")", "").Replace("[", "").Replace("]", "").Replace("{", "").Replace("}", "").Replace("|", "").Replace("\\", "").Replace("/", "").Replace("!", "").Replace("@", "").Replace("#", "").Replace("$", "").Replace("%", "").Replace("^", "").Replace("*", "").Replace("~", "").Replace("`", "").Replace("'", "").Replace("\"", "").Replace("?", "").Replace("<", "").Replace(">", "").Replace(",", "").Replace(".", "").Replace("=", "");
        }

        /***********************************
         * Helper extension method for creating new account
         ***********************************/
        public static void CreateAccount(this DatabaseEntities db, string userName, string fullName, string password, string gravatar)
        {
            ErrorsHelper.IsError = false;
            try
            {
                if (IsEmpty(userName, fullName, password, gravatar)) throw new Exception("Required fields must not be empty.");
                else
                {
                    var anotherUserWithSameUserName = db.Accounts.Where(a => a.UserName == userName).FirstOrDefault() != null;
                    if (anotherUserWithSameUserName) throw new Exception("Please pick another uniqe username.");                    

                    var account = new Account
                            {
                                UserName = userName.ResolveForUserName(),
                                FullName = fullName,
                                Password = BCrypt.HashPassword(password, BCrypt.GenerateSalt(8)),
                                CreationDate = DateTime.Now,
                                UniqueToken = TrackUserToken(db),
                                LoginToken = TrackLoginToken(db),
                                Gravatar = gravatar
                            };

                    db.Accounts.AddObject(account);
                    db.SaveChanges();

                    account.LoginToken.AddCookie(); /* Saving user's login status */

                    db.ValidateCookie();
                }
            }
            catch (Exception ex)
            {
                ex.Message.AlertForError();
            }
        }

        /***********************************
         * Login Helper
         ***********************************/
        public static void Login(this DatabaseEntities db, string userName, string password)
        {
            ErrorsHelper.IsError = false;
            if (IsEmpty(userName, password))
            {
                const string errorMessage = "Required fields must not be empty.";
                errorMessage.AlertForError();
            }
            else
            {
                var user = db.Accounts.Where(a => a.UserName == userName).FirstOrDefault();
                if (user != null && BCrypt.CheckPassword(password, user.Password) == true)
                {
                    user.LoginToken.AddCookie(); /* Saving user's login status */
                    db.ValidateCookie();
                }
                else
                {
                    const string errorMessage = "Either username or password is invalid.";
                    errorMessage.AlertForError();
                }
            }
        }

        /***********************************
         * Validate if any field is null or empty
         ***********************************/
        static bool IsEmpty(params string[] parameters)
        {
            return parameters.Where(string.IsNullOrWhiteSpace).Any();
        }

        /***********************************
         * Validate if user token already taken
         ***********************************/
        static string TrackUserToken(DatabaseEntities db)
        {
            Back:

            var randomNumber = RandomNumbers.GetRandomNumbers();
            var anyAccount = db.Accounts.Where(a => a.UniqueToken == randomNumber).FirstOrDefault();
            if (anyAccount != null) goto Back;

            return randomNumber;
        }

        /***********************************
         * Validate if login-token already taken
         ***********************************/
        static string TrackLoginToken(DatabaseEntities db)
        {
            Back:

            var randomNumber = RandomNumbers.GetRandomNumbers();
            var anyAccount = db.Accounts.Where(a => a.LoginToken == randomNumber).FirstOrDefault();
            if (anyAccount != null) goto Back;

            return randomNumber;
        }

        /***********************************
         * Get account by user's unique (public) token
         ***********************************/
        public static Account GetAccountByUserToken(this string userToken, DatabaseEntities db)
        {
            return db.Accounts.Where(a => a.UniqueToken == userToken).FirstOrDefault();
        }

        /***********************************
         * Saving Account Settings
         ***********************************/
        public static void SaveAccountSettings(this DatabaseEntities db, string fullName, string website, string about)
        {
            ErrorsHelper.IsError = false;
            try
            {
                var currentUser = Static.CurrentUser;
                if (currentUser == null) throw new Exception("You are not logged in.");

                var userAccount = db.Accounts.Where(u => u.UniqueToken == currentUser.UniqueToken).FirstOrDefault();
                if (userAccount == null) throw new Exception("You account not found.");

                if (!string.IsNullOrWhiteSpace(fullName) && fullName != currentUser.FullName) userAccount.FullName = fullName;
                if (website != currentUser.Website) userAccount.Website = website;
                if (about != currentUser.About) userAccount.About = about.Validate();

                db.SaveChanges();
            }
            catch (Exception ex)
            {
                ex.Message.AlertForError();
            }
        }
    }
}